#include <gtest/gtest.h>
#include "scripting/script_interpreter.h"
#include "../sample/battery_level_check.h"
#include "../sample/docking_task.h"
#include "../sample/navigation_task.h"
#include "../sample/screen_return_zero_check.h"
#include "../sample/screen_return_zero_task.h"
#include "../sample/switch_high_current.h"
#include "types/reflex.h"
#include "test_print_info.h"
#include "task/task_chain.h"
#include "task/task_controller.h"

using namespace script;

namespace
{
void printErrorInfo(const ErrorInfo &error_info)
{
    printf("%s\n%d:%d, %s\n\n", error_info.line_code.c_str(), error_info.line, error_info.column, error_info.error_message.c_str());
}
}

class TestFunctionScriptRun: public testing::Test
{
protected:
    std::string scriptPath;
protected:
    void SetUp() override
    {
        REGISTER_TASK_TYPE(BatteryLevelCheck)
        REGISTER_TASK_TYPE(DockingTask)
        REGISTER_TASK_TYPE(NavigationTask)
        REGISTER_TASK_TYPE(ScreenReturnZeroCheck)
        REGISTER_TASK_TYPE(ScreenReturnZeroTask)
        REGISTER_TASK_TYPE(SwitchHighCurrent)
    }
    void TearDown() override
    {
        UNREGISTER_TASK_TYPE(BatteryLevelCheck)
        UNREGISTER_TASK_TYPE(DockingTask)
        UNREGISTER_TASK_TYPE(NavigationTask)
        UNREGISTER_TASK_TYPE(ScreenReturnZeroCheck)
        UNREGISTER_TASK_TYPE(ScreenReturnZeroTask)
        UNREGISTER_TASK_TYPE(SwitchHighCurrent)
    }
};

TEST_F(TestFunctionScriptRun, test_force_function_simple)
{
    const char *code = R"(
        var navigation_task = NavigationTask("navigation_task")
        var docking_task = DockingTask("docking_task")
        var battery_check = BatteryLevelCheck("battery_check")
        var screen_return_zero_task = ScreenReturnZeroTask("screen_return_zero_task")

        function navi()
        {
            while(battery_check)
            {
                docking_task
            }
        }
        navigation_task
        navi
        screen_return_zero_task
    )";
    ScriptInterpreter script_run;
    if (auto scheduler = script_run.interpret(code))
    {
        printf("%s\n", scheduler.value()->toString().c_str());
        scheduler.value()->run();
        SUCCEED();
    }
    else
    {
        printErrorInfo(script_run.getErrorInfo());
        FAIL();
    }
}
